var mouseX=250;
var mouseY=250;
var up, down,left,right,showPercents = false;
if(!vizList){
	var vizList = [];
}


function test(size, x, y, dist, ctx, v){
	this.area = size;
	this.centerX = x;
	this.centerY = y;
	this.radius = Math.sqrt(size/Math.PI);
	this.defaultX = this.centerX+dist/2;
	this.defaultY = this.centerY+dist/2;
	this.x = this.defaultX;
	this.y = this.defaultY;
	this.mouseActivated = false;
	this.ctx = ctx;
	this.v = v;
}

test.prototype.updateTest = function(){
	this.x = this.defaultX;
	this.y = this.defaultY;
    if(this.mouseActivated){
		this.x = mouseX;
		this.y = mouseY;
	}else if(mouseX > this.x-this.radius/3 && mouseX < this.x+this.radius/3 && mouseY > this.y-this.radius/3 && mouseY < this.y+this.radius/3){
		this.mouseActivated = true;
	}
	
	if(up){
		this.radius++
		this.area = Math.pow(this.radius,2)*Math.PI;
	}else if(down){
		this.radius = this.radius<=1 ? 0 : this.radius-1
		this.area = Math.pow(this.radius,2)*Math.PI;
	}
	
	if(euclidDistance(this.x, this.y, this.centerX, this.centerY) > this.radius+this.v.sickRadius){
		var angle = Math.atan2(mouseY - this.centerY, mouseX-this.centerX);
		this.x = Math.cos(angle)*(this.radius+v.sickRadius)+this.centerX;
		this.y = Math.sin(angle)*(this.radius+v.sickRadius)+this.centerY;
	}
}

test.prototype.drawTest = function(){
    this.ctx.save();
	this.ctx.fillStyle = 'rgba(0,0,255,.5)';
	this.ctx.strokeStyle = 'rgba(0,0,255,0)';
	this.ctx.beginPath();
	//this.sickRadius = Math.sqrt(this.sickArea/Math.PI);
	this.ctx.arc(this.x,this.y,this.radius,0,2*Math.PI);
	this.ctx.fill();
	this.ctx.closePath();
	this.ctx.restore();
	this.ctx.lineWidth = 2;
}

//arguments must add up to one
function Viz(falseNeg,truePos,falsePos,trueNeg, interactable, showTopBrackets, showBottomBrackets, drawNumbers, canvasId, showBar){
	this.c=document.getElementById(canvasId);
	this.ctx=this.c.getContext("2d");
	this.ctx.lineWidth = 2;
	this.showBar = showBar;
	this.showTopBrackets = showTopBrackets;
	this.showBottomBrackets = showBottomBrackets;
	this.numTrials = 100;
	this.drawNumbers = drawNumbers;
	this.labelBuffer = 100;
	this.size = 150*Math.min(this.c.height, this.c.width-this.labelBuffer);
	this.ratioHealthy = falsePos+trueNeg;
	this.healthyArea = this.ratioHealthy*this.size;
	this.sickArea = (1-this.ratioHealthy)*this.size;
	this.healthRadius = Math.sqrt((this.sickArea+this.healthyArea)/Math.PI);
	this.sickRadius = Math.sqrt(this.sickArea/Math.PI);
	this.falsePosRatio = falsePos;
	this.truePosRatio = truePos;
	this.falseNegRatio = falseNeg;
	this.trueNegRatio = trueNeg;
	/*if( (showTopBrackets || showBottomBrackets) ){
		this.c.width += this.labelBuffer;
	}*/
	this.centerX = showTopBrackets ? (this.c.width-this.labelBuffer/2)/2 : (this.c.width/2) ;
	this.centerY = showBar ? this.c.height*(1/3) : (this.c.height/2)+17;
	if(showTopBrackets){
		this.centerY -= 15;
	}
	
	this.testArea = (truePos+falsePos)*this.size;
	this.testRadius = Math.sqrt((this.testArea)/Math.PI);
	r1 = Math.max(this.testRadius, this.sickRadius);
	r2 = Math.min(this.testRadius, this.sickRadius);
	//console.log(r1);
	//console.log(r2);
	var dist = findDistanceBetweenCircles(r1, r2, r1-r2, r1+r2, truePos*this.size);
	this.testCircle = new test(this.testArea, this.centerX, this.centerY, dist, this.ctx, this);
	if(interactable){
		setInterval(update, 60);
	}
	vizList.push(this);
	update();
}



Viz.prototype.resize = function(healthy,sick){
	if(sick >= this.size || sick<0) return;
	this.totalPeople = healthy+sick;
	this.ratioHealthy = healthy/this.totalPeople;
	this.healthyArea = this.ratioHealthy*this.size;
	this.sickArea = (1-this.ratioHealthy)*this.size;
	this.healthRadius = Math.sqrt((this.sickArea+this.healthyArea)/Math.PI);
}

Viz.prototype.drawBasic = function(){	
	this.ctx.fillStyle="#FF0000";
	this.ctx.lineWidth = 2;
	this.ctx.beginPath();
	var ratioSick = 1-this.ratioHealthy;
	this.healthRadius = Math.sqrt((this.sickArea+this.healthyArea)/Math.PI); //relationship between health and sick radii
	this.ctx.arc(this.centerX,this.centerY,this.healthRadius,0,2*Math.PI);
	this.ctx.closePath();
	this.ctx.stroke();
	
	this.ctx.beginPath();
	this.sickRadius = Math.sqrt(this.sickArea/Math.PI);
	this.ctx.arc(this.centerX,this.centerY,this.sickRadius,0,2*Math.PI);
	this.ctx.closePath();
	this.ctx.fill();
	
}

Viz.prototype.drawTest = function(){	
	this.drawBasic();
	
	this.testCircle.drawTest();

	//this.drawFill();
	
}

Viz.prototype.updateViz = function(){
	var inc = this.size*0.01
	if(left){
		this.resize(this.healthyArea+inc, this.sickArea-inc)
	}else if(right){
		this.resize(this.healthyArea-inc, this.sickArea+inc)
	}
	
	if(this.showBottomBrackets){
		this.drawLabel("Sick People", this.centerX-this.healthRadius-85, this.centerY, this.centerX, this.centerY, this.sickRadius, 9, false, true);
		this.drawLabel("Healthy People", this.centerX-this.healthRadius-65,this.centerY-this.healthRadius+20, this.centerX, this.centerY, this.healthyRadius, 10,false, true);
	}
	if(this.showTopBrackets){
		//name, x, y, isBracket, isGoingRight
		this.drawLabel("Tested Sick", this.healthRadius+this.centerX+20, this.testCircle.y, this.testCircle.x, this.testCircle.y, this.testCircle.radius, 10, true, false);
	}
	
	sin = Math.sqrt(2)/2;
	cos = Math.sqrt(2)/2;
	
	this.ctx.save();
	var fontSize = 12;
	this.ctx.font = fontSize+"px Arial";
	if(this.drawNumbers){
		var pos = lerp(this.centerX-this.sickRadius*cos, this.centerY-this.sickRadius*sin, this.testCircle.x-this.testCircle.radius*cos, this.testCircle.y-this.testCircle.radius*sin, 0.5);
		this.ctx.fillText(Math.round(this.falseNegRatio*200)+"%", pos.x, pos.y);
		this.ctx.save()
		this.ctx.fillStyle = 'white';
		var pos = lerp(this.centerX+this.sickRadius*cos, this.centerY+this.sickRadius*sin, this.testCircle.x-this.testCircle.radius*cos, this.testCircle.y-this.testCircle.radius*sin, 0.5);
		this.ctx.fillText(Math.round(this.truePosRatio*200)+"%", pos.x, pos.y);
		this.ctx.restore();
		var pos = lerp(this.centerX+this.sickRadius*cos, this.centerY+this.sickRadius*sin, this.testCircle.x+this.testCircle.radius*cos, this.testCircle.y+this.testCircle.radius*sin, 0.5);
		this.ctx.fillText(Math.round(this.falsePosRatio*200)+"%",pos.x, pos.y);
		var pos = lerp(this.centerX, this.centerY, this.centerX, this.centerY-this.healthRadius, 0.8);
		this.ctx.fillText(Math.round(this.trueNegRatio*200)+"%", pos.x-10, pos.y);
	}
	this.ctx.restore();
}

Viz.prototype.drawBars = function(){
	var t = this.testCircle;
	var totalArea = this.sickArea+this.healthyArea;
	this.totalArea = totalArea;
	var distance = Math.sqrt(Math.pow(this.centerX-t.x,2)+Math.pow(this.centerY-t.y,2));
	var sickRadius = Math.sqrt(this.sickArea/Math.PI);
	var intersectingArea = getAreaOfIntersectingCircles(distance, t.radius, sickRadius);
	if(isNaN(intersectingArea)){
		intersectingArea = t.area < this.sickArea ? t.area : this.sickArea
		if(distance >= t.radius+this.sickRadius) intersectingArea = 0;
	}
	var areaInTotalCircle = getAreaOfIntersectingCircles(distance, t.radius, this.healthRadius);
	if(isNaN(areaInTotalCircle)){
		areaInTotalCircle = t.area < totalArea ? t.area : totalArea;
		if(distance >= t.radius+this.healthRadius) areaInTotalCircle = 0;
	}
	var fn = this.sickArea-intersectingArea; //false negative
	//var fp = areaInTotalCircle-intersectingArea; //false positive
	var fp = t.area-intersectingArea;
	if(fp > this.healthyArea) fp = this.healthyArea;
	var tn = this.healthyArea-fp //true negative
	var tp = intersectingArea //true positive
	
	var start = this.c.width/8;
	var barLength = this.c.width*(3/4);
	var barWidth = 30;
	var barHeight = this.c.height*(2/3)+barWidth;
	this.barWidth = barWidth;
	var sickBar = this.sickArea/totalArea*barLength;
	var healthyBar = this.healthyArea/totalArea*barLength;
	var fnBar = fn/totalArea*barLength;
	var fbBar = fp/totalArea*barLength;
	var intersectBar = tp/totalArea*barLength;
	this.ctx.save();
	this.ctx.fillStyle = "red";
	this.ctx.fillRect(start, barHeight, fnBar+intersectBar, barWidth);
	this.ctx.fillStyle = 'rgba(0,0,255,.5)';
	this.ctx.fillRect(start+fnBar, barHeight-4, fbBar+intersectBar, barWidth+8);
	this.ctx.strokeRect(start+fnBar, barHeight-4, fbBar+intersectBar, barWidth+8);
	this.ctx.strokeStyle = 'black'
	this.ctx.lineWidth = 2;
	this.ctx.strokeRect(start, barHeight, sickBar, barWidth)
	this.ctx.strokeRect(start+sickBar, barHeight, healthyBar, barWidth)
	
	
	//draw sick bracket
	this.ctx.closePath();
	this.ctx.fillStyle = "black"
	
	if(this.showBottomBrackets){
		this.drawBracket("Sick People", start, start+sickBar-2, false, barHeight, 10);
		this.drawBracket("Healthy People", start+sickBar+2, healthyBar+start+sickBar, false, barHeight, 10);
	}
	if(this.showTopBrackets){
		this.drawBracket("Tested Sick", start+fnBar+2, start+fnBar+intersectBar+fbBar-2, true, barHeight-7, 15);
		//this.drawBracket("Tested Healthy", start+fnBar+intersectBar+fbBar+2, healthyBar+start+sickBar, true, barHeight, 10);
		//this.drawBracket("Tested Healthy", start, start+fnBar-2, true, barHeight, 10);
	}
	
	//write percentages on bar
	if(!showPercents){
		this.ctx.restore();
		return;
	}
	var tpString = Math.round(tp/totalArea*100)+"%";
	if(Math.round(tp/totalArea*100) > 0){
		this.ctx.fillText(tpString, start+fnBar+(intersectBar/2)-(tpString.length*2), barHeight+13);
	}
	var fnString = Math.round(fn/totalArea*100)+"%";
	if(Math.round(fn/totalArea*100) > 0){
		this.ctx.fillText(fnString, start+(fnBar/2)-(fnString.length*2), barHeight+13);
	}
	var fpString = Math.round(fp/totalArea*100)+"%";
	if(Math.round(fp/totalArea*100) > 0){
		this.ctx.fillText(fpString, start+fnBar+intersectBar+(fbBar/2)-(fpString.length*2), barHeight+13);
	}
	var tnString = Math.round(tn/totalArea*100)+"%";
	if(Math.round(tn/totalArea*100) > 0){
		this.ctx.fillText(tnString, start+fnBar+intersectBar+fbBar+((barLength-(start+fnBar+intersectBar+fbBar))/2)+(tpString.length*2), barHeight+13);
	}
	
	this.ctx.restore();
	
	
	
	/*this.ctx.fillStyle = 'rgba(10,10,10,1)';
	this.ctx.font = "bold 18px sans-serif";
	this.ctx.fillText("Correct", 100, 25);
	this.ctx.fillText("Incorrect", 300, 25);
	this.ctx.font = "bold 12px sans-serif";
	this.ctx.fillStyle = 'rgba(153,25,25,1)';
	this.ctx.fillText("Positive: "+Math.round(tp/totalArea*100)+"%", 105, 45);
	this.ctx.fillStyle = 'black';
	this.ctx.fillText("Negative: "+Math.round(tn/totalArea*100)+"%", 105, 65);
	this.ctx.fillStyle = 'rgba(50,50,50,.5)';
	this.ctx.fillText("Positive: "+Math.round(fp/totalArea*100)+"%", 305, 45);
	this.ctx.fillStyle = 'red';
	this.ctx.fillText("Negative: "+Math.round(fn/totalArea*100)+"%", 305, 65);*/
}

Viz.prototype.drawLabel = function(name, x, y, circleX, circleY, radius, bracketLength,isBracket, isGoingRight){
	this.ctx.fillStyle = 'black';
	var fontSize = 14;
	this.ctx.font = fontSize+"px Arial";
	var length = name.length*(fontSize/2);
	this.ctx.fillText(name, x, y+fontSize/4);
	this.ctx.save();
	if(isBracket){
		//this.ctx.translate(circleX,circleY);
		//var angle = isGoingRight ? Math.atan2(circleY-y,circleX-x) : Math.atan2(y-circleY,x-circleX);
		//this.ctx.rotate(angle);
		//this.ctx.translate(-circleX,-circleY);
		//console.log(Math.sin(angle));
		this.ctx.save();
		var buffer = this.ctx.lineWidth+4;
		this.ctx.beginPath(); 
		var startX = isGoingRight ? x+length : x;
		var endX = isGoingRight ? this.centerX - this.healthRadius - bracketLength : this.centerX + this.healthRadius + bracketLength;
		this.ctx.moveTo(startX, circleY);
		this.ctx.lineTo(endX, circleY);
		this.ctx.lineTo(endX, circleY+radius-buffer);
		var bracketEndX = isGoingRight ? endX + bracketLength : endX - bracketLength;
		var dashedBracketEndX = isGoingRight ? circleX : circleX;
		this.ctx.lineTo(bracketEndX, circleY+radius-buffer);
		this.ctx.moveTo(endX, circleY);
		this.ctx.lineTo(endX, circleY-radius+buffer);
		this.ctx.lineTo(bracketEndX, circleY-radius+buffer);
		
		this.ctx.dashedLine(endX, circleY-radius+buffer, dashedBracketEndX+40, circleY-radius+buffer, 4);
		this.ctx.dashedLine(endX, circleY+radius-buffer, dashedBracketEndX+40, circleY+radius-buffer, 4);
		this.ctx.lineWidth = 2;
		this.ctx.closePath(); 
		this.ctx.stroke();
		this.ctx.restore();
		this.ctx.moveTo(startX,y);
		//this.ctx.lineTo(0,0);
		//this.ctx.lineTo(Math.cos(angle)*(endX-dashedBracketEndX)+circleX, Math.sin(angle)*(endX-dashedBracketEndX)+circleY);
		
	}else{
		this.ctx.save();
		this.ctx.lineWidth = 2;
		var startX = isGoingRight ? x+length : x;
		this.ctx.beginPath();
		this.ctx.moveTo(startX, y);
		var deltaX = (circleY-y)/2;
		var endX = circleX+deltaX-75+bracketLength; //Does not account for going right
		this.ctx.lineTo(endX, y);
		this.ctx.closePath();
		this.ctx.stroke();
		this.ctx.restore();
	}
	//this.ctx.stroke();
	
	
	//this.ctx.beginPath(); 
	//this.ctx.arc(x+length,y-fontSize/4, radius, 0, 2*Math.PI);
	//this.ctx.stroke();
	//this.ctx.fill();
	this.ctx.restore();
}

var lerp = function(startX, startY, endX, endY, time){
   return {x: startX + time*(endX-startX), y:startY + time*(endY-startY)};
}

Viz.prototype.drawBracket = function(name, start, end, isOnTop, barHeight, legLength){
	this.ctx.save();
	this.ctx.fillStyle = 'black';
	this.ctx.font = "14px Arial";
	if(end-start < 1) return;
	var ctx = this.ctx;
	//draw intersection bracket
	midPoint = start+(end-start)/2;
	minHeight = isOnTop ? barHeight-15+legLength: barHeight+this.barWidth+15-legLength
	maxHeight = isOnTop ? barHeight-15 : barHeight+this.barWidth+15
	notchHeight = isOnTop ? barHeight-25 : barHeight+this.barWidth+25
	textHeight = isOnTop ? barHeight-27 : barHeight+this.barWidth+40
	ctx.beginPath();
	ctx.moveTo(start, minHeight);
	ctx.lineTo(start, maxHeight);
	ctx.lineTo(end, maxHeight);
	ctx.lineTo(end, minHeight);
	ctx.moveTo(midPoint, maxHeight)
	ctx.lineTo(midPoint, notchHeight)
	ctx.fillText(name, midPoint-(name.length)*(3.4), textHeight) //sub 25 to center the text
	ctx.stroke();
	ctx.restore();
	
	
}

Viz.prototype.drawBullets = function(distance){
	//var fn = this.falseNeg*this.numTrials; //A-B
	//sickArea = A, B = test area, A intersect B = true positives
	var fp = this.falsePosRatio*this.size; //B-A
	var tp = this.truePosRatio*this.size; //A intersect B
	var fn = this.sickArea-tp; //A-B
	
	//console.log("fn: "+fn+", fp: "+fp+", tp: "+ tp)
	var r1 = Math.sqrt((fn+tp)/Math.PI);
	var r2 = Math.sqrt((fp+tp)/Math.PI);
	
	var distance = this.getTestDistance();
	
	this.ctx.fillStyle="#FF0000";
	this.ctx.beginPath();
	this.ctx.arc(this.centerX,this.centerY,r1,0,2*Math.PI);
	this.ctx.stroke();
	
	this.ctx.fillStyle="#FF0000";
	this.ctx.beginPath();
	this.ctx.arc(this.centerX+distance,this.centerY,r2,0,2*Math.PI);
	this.ctx.stroke();
	//http://webhome.cs.uvic.ca/~ruskey/Publications/VennArea/VennArea.pdf
	//find the appropriate distance between the circles
}

Viz.prototype.drawFill = function(){
	var t = this.testCircle;
	var totalArea = this.sickArea+this.healthyArea;
	var distance = Math.sqrt(Math.pow(this.centerX-t.x,2)+Math.pow(this.centerY-t.y ,2));
	var areaInTotalCircle = getAreaOfIntersectingCircles(distance, t.radius, this.healthRadius);
	if(isNaN(areaInTotalCircle)){
		areaInTotalCircle = t.area < totalArea ? t.area : totalArea;
		if(distance > t.radius+this.healthRadius) areaInTotalCircle = 0;
	}
	var intersectingArea = getAreaOfIntersectingCircles(distance, t.radius, this.sickRadius);
	if(isNaN(intersectingArea)){
		intersectingArea = t.area < this.sickArea ? t.area : this.sickArea;
		if(distance > t.radius+this.sickRadius) intersectingArea = 0;
	}
	var area = t.area-areaInTotalCircle;
	
	//dict in the from x1, x2, y1, y2
	var points = getIntersectingPoints(this.healthRadius, t.radius, this.centerX, this.centerY, t.x, t.y);
	
	//starting angles for the two different angles
	var startAngle1 = Math.atan2(points.y1 - this.centerY, points.x1-this.centerX);
	var startAngle2 = Math.atan2(points.y2 - this.centerY, points.x2-this.centerX);
	
	//finds the difference in angles
	var thetaDelta = Math.abs(startAngle1 - startAngle2);
	//Gets the angle in a range of 0 to 2PI instead of -PI to PI
	if(thetaDelta > Math.PI){ 
		thetaDelta = 2*Math.PI - thetaDelta;
	}
	var thetaDeltaDegrees = thetaDelta*(Math.PI/180);
	var wedgeArea = (thetaDelta/2)*Math.pow(this.healthRadius,2) - (thetaDelta/2)*Math.pow(this.sickRadius,2);
	var innerArea = wedgeArea-(areaInTotalCircle-intersectingArea);
	var buffer = 5000/this.sickRadius;
	
	//Check if it is safe to insert wedge
	var smallPoints = getIntersectingPoints(this.sickRadius, t.radius, this.centerX, this.centerY, t.x, t.y); //intersection points between test circle and sick circle
	//var 
	var isFirstPointInWedge = isPointInWedge(startAngle1, startAngle2, smallPoints.x1, smallPoints.y1, this.centerX, this.centerY);
	var isSecondPointInWedge = isPointInWedge(startAngle1, startAngle2, smallPoints.x2, smallPoints.y2, this.centerX, this.centerY);
	
	if(isFirstPointInWedge && isSecondPointInWedge){
		this.ctx.save();
		//this.ctx.fillStyle = 'blue';
		this.ctx.fillStyle = 'rgba(128,128,255,1)'
		//this.drawArcBetweenPoints(this.healthRadius, this.sickRadius, this.centerX, this.centerY, points.x1, points.y1, points.x2, points.y2, true)
		//drawArc(wedgeArea, this.healthRadius, this.sickRadius, this.centerX, this.centerY, startAngle1, true);
		this.ctx.restore();
		area -= innerArea;
	}
	
	this.ctx.save();
	this.ctx.fillStyle = 'rgba(128,128,255,1)'
	//this.drawArc(area/2, this.healthRadius, this.sickRadius, this.centerX, this.centerY, startAngle1, false);
	//this.drawArc(area/2, this.healthRadius, this.sickRadius, this.centerX, this.centerY, startAngle2, true);
	this.ctx.restore();
}

function isPointInWedge(startAngle, endAngle, x, y, centerX, centerY){
	var testAngle = Math.atan2(y-centerY, x-centerX);
	if((endAngle - startAngle) < 0){
		var tmp = endAngle;
		var endAngle = startAngle;
		var startAngle = tmp;
		return !(testAngle < endAngle && testAngle > startAngle);
	}
	return (testAngle < endAngle && testAngle > startAngle);
}

//Draws the excess area as an arc around the small circle
Viz.prototype.drawArc = function(area, bigR, smallR, centerX, centerY, startAngle, clockwise){
	var theta = area/(bigR-smallR)/360*2.37;
	start = clockwise ? startAngle : startAngle-theta;
	end   = clockwise ? theta+startAngle : startAngle;
	this.ctx.save();
	//this.ctx.fillStyle = 'rgba(153,153,153,1)'
	this.ctx.beginPath();
	this.ctx.lineWidth = 10;
	this.ctx.moveTo(centerX+Math.cos(start)*smallR, centerY+Math.sin(start)*smallR);
	this.ctx.lineTo(centerX+Math.cos(start)*bigR, centerY+Math.sin(start)*bigR);
    this.ctx.arc(centerX, centerY, bigR, start, end, false);
    this.ctx.lineTo(smallR*Math.cos(end)+centerX,smallR*Math.sin(end)+centerY);
   	this.ctx.arc(centerX, centerY, smallR, end, start, true);
    this.ctx.fill();
    this.ctx.restore();
}

function getEndAngle(area, bigR, smallR, centerX, centerY, startAngle, clockwise){
	var theta = area/(bigR-smallR)/360*2.37;
	end = theta+startAngle;
	return end;
}

//Draws an arc between two points on a circle
Viz.prototype.drawArcBetweenPoints = function(bigR, smallR, centerX, centerY, x1, y1, x2, y2){
	var start = Math.atan2(y1 - centerY, x1-centerX);
	var end = Math.atan2(y2 - centerY, x2-centerX);
	this.ctx.save();
	//this.ctx.fillStyle = 'rgba(153,153,153,1)'
	this.ctx.beginPath();
	this.ctx.lineWidth = 10;
	this.ctx.moveTo(centerX+Math.cos(start)*smallR, centerY+Math.sin(start)*smallR);
	this.ctx.lineTo(centerX+Math.cos(start)*bigR, centerY+Math.sin(start)*bigR);
    this.ctx.arc(centerX, centerY, bigR, start, end, false);
    this.ctx.lineTo(smallR*Math.cos(end)+centerX,smallR*Math.sin(end)+centerY);
   	this.ctx.arc(centerX, centerY, smallR, end, start, true);
    this.ctx.fill();
    this.ctx.restore();
}

//gets the intersecting points between two circles
//rn = radius of the circle
//returns a dict with the form x1, y1, x2, y2 containing the coords for all intersecting points
//solution found at http://stackoverflow.com/questions/3349125/circle-circle-intersection-points
function getIntersectingPoints(r1, r2, x1, y1, x2, y2){
	var distance = euclidDistance(x1,y1,x2,y2);
	//circle do not intersect
	//pick the closest point on the first circle
	if(distance >= r1+r2){
		var theta = Math.atan2(y2 - y1, x2-x1);
		var x = Math.cos(theta)*r1+x1;
		var y = Math.sin(theta)*r1+x1;
		return {x1: x, y1:y, x2:x, y2:y}
	}
	var a = (Math.pow(r1,2) - Math.pow(r2,2) + Math.pow(distance,2)) / (2*distance);
	var h = Math.sqrt(Math.pow(r1,2)-Math.pow(a,2));
	var midX = x1+a*(x2-x1)/distance;
	var midY = y1+a*(y2-y1)/distance;
	//calculate intersection points
	var intX1 = midX + h*(y2-y1)/distance;
	var intY1 = midY - h*(x2-x1)/distance;
	var intX2 = midX - h*(y2-y1)/distance;
	var intY2 = midY + h*(x2-x1)/distance;
	return {x1: intX1, y1:intY1, x2:intX2, y2:intY2}
}

function euclidDistance(x1, y1, x2, y2){
	return Math.sqrt(Math.pow(x1-x2,2)+Math.pow(y1-y2,2));
}

Viz.prototype.drawClippingCircle = function(){
	// Create a circle
	this.ctx.save();
    this.ctx.beginPath();
    this.ctx.arc(this.centerX, this.centerY, this.healthRadius+1, 0, Math.PI * 2, false);
 
    // Clip to the current path
    this.ctx.clip();
}

//finds the distance between two circles.
//It is used to find the distance apart from eachother two circles need to be in order for
//the area of the overlap to equal the proper intersection (ie. number of true positives)
function findDistanceBetweenCircles(r1, r2, minDistance, maxDistance, targetArea){
	var maxArea = getAreaOfIntersectingCircles(minDistance, r1, r2);
	var minArea = getAreaOfIntersectingCircles(maxDistance, r1, r2);
	var midArea = Math.abs(maxArea+minArea)/2;
	var buffer = 1;
	var midDistance = Math.abs(maxDistance+minDistance)/2;
	var area = getAreaOfIntersectingCircles(midDistance, r1, r2);
	//console.log(area);
	if(area-buffer < targetArea && targetArea < area+buffer){
		return midDistance;
	}else if(targetArea >= area){
		return findDistanceBetweenCircles(r1, r2, minDistance, midDistance, targetArea)
	}else if(targetArea <= area){
		return findDistanceBetweenCircles(r1, r2, midDistance, maxDistance, targetArea)
	}
	
	console.log('this shouldnt happen');
}

//r1 and r2 are the radii of the two circles and d is their distance apart
function getAreaOfIntersectingCircles(d,r1,r2){
	var alpha = 2*Math.acos((Math.pow(d,2)+Math.pow(r1, 2)-Math.pow(r2,2))/(2*r1*d));
	var beta = 2*Math.acos((Math.pow(d,2)+Math.pow(r2, 2)-Math.pow(r1,2))/(2*r2*d));
	var area = (1/2)*Math.pow(r1,2)*(alpha-Math.sin(alpha)) + (1/2)*Math.pow(r2,2)*(beta-Math.sin(beta))
	
	//console.log("area: "+area+", alpha: "+alpha+", beta: "+ beta)
	//console.log("d: "+d+", r1: "+r1+", r2: "+ r2)
	return area;
}

function update(){
	for(i in vizList){
		vizList[i].c.width = vizList[i].c.width;
		vizList[i].testCircle.updateTest();
		if(vizList[i].showBar){
			vizList[i].drawBars();
		}
		vizList[i].drawClippingCircle();
		vizList[i].drawTest();
		vizList[i].ctx.restore();
		vizList[i].updateViz();
	}
}

function detectMousePosition(evt){
	if (evt.offsetX) {
        mouseX = evt.offsetX;
        mouseY = evt.offsetY;
    }
    else if (evt.layerX) {
        mouseX = evt.layerX;
        mouseY = evt.layerY;
    }
    
}

function doKeyDown(evt){
	switch (evt.keyCode) {
		case 87:  /* Up arrow was pressed */
			up = true;
		break;
		case 83:  /* Down arrow was pressed */
			down = true;
		break;
		case 65:  /* Left arrow was pressed */
			left = true;
		break;
		case 68:  /* Right arrow was pressed */
			right = true;
		break;
		case 90:
			showPercents = true;
		break;
	}
}


function doKeyUp(evt){
	switch (evt.keyCode) {
		case 87:  /* Up arrow was pressed */
			up = false;
		break;
		case 83:  /* Down arrow was pressed */
			down = false;
		break;
		case 65:  /* Left arrow was pressed */
			left = false;
		break;
		case 68:  /* Right arrow was pressed */
			right = false;
		break;
		case 90:
			showPercents = false;
		break;
	}
}
//Taken from http://stackoverflow.com/questions/15397036/drawing-dashed-lines-on-html5-canvas
CanvasRenderingContext2D.prototype.dashedLine = function (x1, y1, x2, y2, dashLen) {
    if (dashLen == undefined) dashLen = 2;
    this.moveTo(x1, y1);

    var dX = x2 - x1;
    var dY = y2 - y1;
    var dashes = Math.floor(Math.sqrt(dX * dX + dY * dY) / dashLen);
    var dashX = dX / dashes;
    var dashY = dY / dashes;

    var q = 0;
    while (q++ < dashes) {
        x1 += dashX;
        y1 += dashY;
        this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x1, y1);
    }
    this[q % 2 == 0 ? 'moveTo' : 'lineTo'](x2, y2);
};

window.addEventListener('mousemove', detectMousePosition,true);
window.addEventListener('keydown',doKeyDown,true);
window.addEventListener('keyup',doKeyUp,true);
//var v = new Viz(0.1, 0.4, 0.1, 0.4, true, true, true, "myCanvas", true); //falsePos, truePos, falseNeg, trueNeg
